"""
断言引擎模块
支持多种断言类型：状态码、响应体字段、响应时间等
"""

from typing import Dict, Any, List, Tuple
import re


class AssertionEngine:
    """断言引擎"""
    
    @staticmethod
    def execute_assertion(assertion: Dict[str, Any], response: Dict[str, Any]) -> Tuple[bool, str]:
        """
        执行单个断言
        
        Args:
            assertion: 断言规则
            response: 响应数据，包含status_code、body、response_time等
            
        Returns:
            (是否通过, 错误信息)
        """
        assertion_type = assertion.get('type', '')
        
        if assertion_type == 'status_code':
            return AssertionEngine._assert_status_code(assertion, response)
        
        elif assertion_type == 'field_exists':
            return AssertionEngine._assert_field_exists(assertion, response)
        
        elif assertion_type == 'field_value':
            return AssertionEngine._assert_field_value(assertion, response)
        
        elif assertion_type == 'response_time':
            return AssertionEngine._assert_response_time(assertion, response)
        
        elif assertion_type == 'body_contains':
            return AssertionEngine._assert_body_contains(assertion, response)
        
        elif assertion_type == 'regex':
            return AssertionEngine._assert_regex(assertion, response)
        
        else:
            return False, f"不支持的断言类型: {assertion_type}"
    
    @staticmethod
    def execute_assertions(assertions: List[Dict[str, Any]], response: Dict[str, Any]) -> Dict[str, Any]:
        """
        执行多个断言
        
        Args:
            assertions: 断言规则列表
            response: 响应数据
            
        Returns:
            断言结果汇总
        """
        results = {
            'total': len(assertions),
            'passed': 0,
            'failed': 0,
            'details': []
        }
        
        for assertion in assertions:
            passed, error_msg = AssertionEngine.execute_assertion(assertion, response)
            
            result_detail = {
                'assertion': assertion,
                'passed': passed,
                'error_msg': error_msg if not passed else None
            }
            
            results['details'].append(result_detail)
            
            if passed:
                results['passed'] += 1
            else:
                results['failed'] += 1
        
        return results
    
    @staticmethod
    def _assert_status_code(assertion: Dict[str, Any], response: Dict[str, Any]) -> Tuple[bool, str]:
        """断言状态码"""
        expected = assertion.get('expected')
        actual = response.get('status_code')
        operator = assertion.get('operator', '==')
        
        if operator == '==':
            passed = actual == expected
        elif operator == '!=':
            passed = actual != expected
        elif operator == '>':
            passed = actual > expected
        elif operator == '<':
            passed = actual < expected
        elif operator == '>=':
            passed = actual >= expected
        elif operator == '<=':
            passed = actual <= expected
        else:
            return False, f"不支持的操作符: {operator}"
        
        if not passed:
            return False, f"状态码断言失败: 期望{operator}{expected}, 实际{actual}"
        
        return True, ""
    
    @staticmethod
    def _assert_field_exists(assertion: Dict[str, Any], response: Dict[str, Any]) -> Tuple[bool, str]:
        """断言字段存在性"""
        field = assertion.get('field', '')
        body = response.get('body', {})
        
        if not isinstance(body, dict):
            return False, f"响应体不是字典格式，无法检查字段: {field}"
        
        # 支持嵌套字段，如 "data.user.name"
        fields = field.split('.')
        current = body
        
        for f in fields:
            if isinstance(current, dict) and f in current:
                current = current[f]
            else:
                return False, f"字段不存在: {field}"
        
        return True, ""
    
    @staticmethod
    def _assert_field_value(assertion: Dict[str, Any], response: Dict[str, Any]) -> Tuple[bool, str]:
        """断言字段值"""
        field = assertion.get('field', '')
        expected = assertion.get('expected')
        operator = assertion.get('operator', '==')
        body = response.get('body', {})
        
        if not isinstance(body, dict):
            return False, f"响应体不是字典格式，无法检查字段值: {field}"
        
        # 获取字段值（支持嵌套）
        fields = field.split('.')
        current = body
        
        for f in fields:
            if isinstance(current, dict) and f in current:
                current = current[f]
            else:
                return False, f"字段不存在: {field}"
        
        actual = current
        
        # 执行比较
        try:
            if operator == '==':
                passed = actual == expected
            elif operator == '!=':
                passed = actual != expected
            elif operator == '>':
                passed = actual > expected
            elif operator == '<':
                passed = actual < expected
            elif operator == '>=':
                passed = actual >= expected
            elif operator == '<=':
                passed = actual <= expected
            elif operator == 'contains':
                passed = expected in str(actual)
            else:
                return False, f"不支持的操作符: {operator}"
            
            if not passed:
                return False, f"字段值断言失败: {field} 期望{operator}{expected}, 实际{actual}"
            
            return True, ""
            
        except Exception as e:
            return False, f"字段值比较失败: {str(e)}"
    
    @staticmethod
    def _assert_response_time(assertion: Dict[str, Any], response: Dict[str, Any]) -> Tuple[bool, str]:
        """断言响应时间"""
        expected = assertion.get('expected')  # 毫秒
        actual = response.get('response_time', 0)  # 毫秒
        operator = assertion.get('operator', '<')
        
        if operator == '<':
            passed = actual < expected
        elif operator == '<=':
            passed = actual <= expected
        elif operator == '>':
            passed = actual > expected
        elif operator == '>=':
            passed = actual >= expected
        else:
            return False, f"不支持的操作符: {operator}"
        
        if not passed:
            return False, f"响应时间断言失败: 期望{operator}{expected}ms, 实际{actual}ms"
        
        return True, ""
    
    @staticmethod
    def _assert_body_contains(assertion: Dict[str, Any], response: Dict[str, Any]) -> Tuple[bool, str]:
        """断言响应体包含指定内容"""
        expected = assertion.get('expected', '')
        body = response.get('body', '')
        
        # 将body转换为字符串
        if isinstance(body, dict) or isinstance(body, list):
            import json
            body_str = json.dumps(body, ensure_ascii=False)
        else:
            body_str = str(body)
        
        if expected not in body_str:
            return False, f"响应体不包含期望内容: {expected}"
        
        return True, ""
    
    @staticmethod
    def _assert_regex(assertion: Dict[str, Any], response: Dict[str, Any]) -> Tuple[bool, str]:
        """断言正则表达式匹配"""
        pattern = assertion.get('pattern', '')
        field = assertion.get('field', '')
        body = response.get('body', {})
        
        # 如果指定了字段，从字段中获取值
        if field:
            if not isinstance(body, dict):
                return False, f"响应体不是字典格式，无法检查字段: {field}"
            
            fields = field.split('.')
            current = body
            
            for f in fields:
                if isinstance(current, dict) and f in current:
                    current = current[f]
                else:
                    return False, f"字段不存在: {field}"
            
            value = str(current)
        else:
            # 否则对整个响应体进行匹配
            if isinstance(body, dict) or isinstance(body, list):
                import json
                value = json.dumps(body, ensure_ascii=False)
            else:
                value = str(body)
        
        try:
            if not re.search(pattern, value):
                return False, f"正则表达式匹配失败: 模式'{pattern}' 未匹配到内容"
            
            return True, ""
            
        except re.error as e:
            return False, f"正则表达式错误: {str(e)}"
